#include "iuMacAddress.hpp"
#include <cstdio>
#include <cstring>
#include "iuIPAddress.hpp"

/**
 * @brief Constructeur de iuMacAddress. Initialise l'adresse a 00:00:00:00:00:00
 */
iuMacAddress::iuMacAddress()
{
   for (int i = 0; i < 6; i++)
      m_address[i] = 0;
}

/**
 * @brief Attribue les differents octets de l'adresse MAC
 * @param addr1 le 1er octet de l'adresse
 * @param addr2 le 2nd octet de l'adresse
 * @param addr3 le 3eme octet de l'adresse
 * @param addr4 le 4eme octet de l'adresse
 * @param addr5 le 5eme octet de l'adresse
 * @param addr6 le 6eme octet de l'adresse
 */
void iuMacAddress::set(uint8_t addr1, uint8_t addr2, uint8_t addr3, uint8_t addr4, uint8_t addr5, uint8_t addr6)
{
   m_address[0] = addr1;
   m_address[1] = addr2;
   m_address[2] = addr3;
   m_address[3] = addr4;
   m_address[4] = addr5;
   m_address[5] = addr6;
}

/**
 * @brief Recupere les differents octets de l'adresse MAC
 * @param addr1 l'adresse ou placer le 1er octet de l'adresse. Peut etre NULL
 * @param addr2 l'adresse ou placer le 2nd octet de l'adresse. Peut etre NULL
 * @param addr3 l'adresse ou placer le 3eme octet de l'adresse. Peut etre NULL
 * @param addr4 l'adresse ou placer le 4eme octet de l'adresse. Peut etre NULL
 * @param addr5 l'adresse ou placer le 5eme octet de l'adresse. Peut etre NULL
 * @param addr6 l'adresse ou placer le 6eme octet de l'adresse. Peut etre NULL
 */
void iuMacAddress::get(uint8_t *addr1, uint8_t *addr2, uint8_t *addr3, uint8_t *addr4, uint8_t *addr5, uint8_t *addr6) const
{
   if (addr1)   *addr1 = m_address[0];
   if (addr2)   *addr2 = m_address[1];
   if (addr3)   *addr3 = m_address[2];
   if (addr4)   *addr4 = m_address[3];
   if (addr5)   *addr5 = m_address[4];
   if (addr6)   *addr6 = m_address[5];
}

/**
 * @brief Construit l'adresse MAC a partir d'une adresse IP, d'un PID et d'un numero d'interface:
 * Les 4 premiers octets de l'adresse MAC correspondent a l'adresse IP, le 5eme au PID (modulo 256)
 * et le dernier au numero d'interface
 * @param ip l'adresse IP a utiliser pour construire l'adresse MAC
 * @param pid le PID a utiliser pour construire l'adresse MAC
 * @param interface le numero d'interface a utiliser pour construire l'adresse MAC
 */
void iuMacAddress::build(const iuIPAddress &ip, pid_t pid, unsigned char interface)
{
   ip.toBuffer((char *)m_address);
   m_address[4] = pid & 0xff;
   m_address[5] = interface;
}

/**
 * @brief Attribue a l'adresse MAC la valeur de l'adresse de broadcast (FF:FF:FF:FF:FF:FF)
 */
void iuMacAddress::setToBroadcast()
{
   for (int i = 0; i < 6; i++)
      m_address[i] = 0xff;
}

/**
 * @brief Teste si les deux adresses MAC sont egales
 * @param addr la deuxieme adresse MAC a comparer
 * @return Renvoie true si les deux adresses MAC sont egales, false sinon
 */
bool iuMacAddress::operator==(const iuMacAddress &addr) const
{
   for (int i = 0; i < 6; i++)
   {
      if (m_address[i] != addr.m_address[i])
         return false;
   }
   
   return true;
}

/**
 * @brief Teste si l'adresse MAC est l'adresse de broadcast (i.e. FF:FF:FF:FF:FF:FF)
 * @return Renvoie true si l'adresse est l'adresse de broadcast, false sinon
 */
bool iuMacAddress::isBroadcast() const
{
   for (int i = 0; i < 6; i++)
   {
      if (m_address[i] != 0xff)
         return false;
   }
   
   return true;
}

/**
 * @brief Lit l'adresse MAC a partir d'un buffer (d'au moins 6 octets)
 * @param buffer l'adresse du debut du buffer
 * @return Renvoie le nombre d'octets lus (ici, 6)
 */
uint16_t iuMacAddress::fromBuffer(const char *buffer)
{
   memcpy(m_address, buffer, 6);
   return 6;
}

/**
 * @brief Ecrit l'adresse MAC dans un buffer (d'au moins 6 octets)
 * @param buffer l'adresse du debut du buffer
 * @return Renvoie le nombre d'octets ecrits dans le buffer (ici, 6)
 */
uint16_t iuMacAddress::toBuffer(char *buffer) const
{
   memcpy(buffer, m_address, 6);
   return 6;
}

/**
 * @brief Convertit l'adresse MAC en chaine de caracteres de la forme AA:BB:CC:DD:EE:FF
 * @return Renvoie la chaine de caracteres
 */
char *iuMacAddress::toString() const
{
   static char str[32];

   sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X",
         m_address[0], m_address[1], m_address[2], m_address[3], m_address[4], m_address[5]);
   return str;
}
